import java.util.*;
/**
 * La clase InfoManager se encarga de administrar la información 
 * entre la interfaz gráfica y los módulos restantes. Los metodos publicos
 * de clase son usados dentro de cualquier codigo de la interfaz gráfica 
 * que los necesite, los metodos de objeto son usados por el código nativo.
 */
public abstract class InfoManager
{
    /**
     * Crea un nuevo objeto de tipo InfoManager encargado de 
     * administrar la información entre el código nativo y la 
     * interfaz gráfica.
     */
    public InfoManager()
    {
        editorMode = new EditorMode();
        memoryMode = new MemoryMode();
        mdiMode = new MdiMode();
        fileManagerMode = new FileManagerMode();
        handwheelMode = new HandwheelMode();
        jogMode = new JogMode();
        rapidMode = new RapidMode();
        zeroReturnMode = new ZeroReturnMode();
        data = new Data();
    }
    /**
     * Recibe los valores iniciales de los datos.
     * @param id identificador del dato
     * @param value valor del dato
     */
    public void initData(int id, int value)
    {
        data.initData( id, value);
    }
    public void initData(int id, long value)
    {
        data.initData( id, (long)value);
    }
    /**
     * Recibe los datos iniciales de compensación de trabajo.
     * @param x compensación del eje x.
     * @param y compensación del eje y.
     * @param z compensación del eje z.
     */
    public void initDataWorkOffset(int x, int y, int z)
    {
        data.initWorkOffset(x,y,z);
    }
    /**
     * Recibe los datos iniciales de las compensaciones de las herramientas
     * presentes.
     * @param lenght compensación de la longitud de la herramienta.
     * @param diameter compensación del diámetro de la herramienta.
     */
    public void initDataToolOffset(int lenght, int diameter)
    {
        data.initToolOffset(lenght,diameter);
    }
    /**
     * Proporciona los comandos existentes en cola que son generados por
     * los controles del teclado de la interfaz gáfica.
     * @return un arreglo de dos enteros representando el identificador 
     * del comando y su valor respectivamente.
     */
    public long[] getCommand()
    {
        long[] sendCommand = removeCommand();
        long id  = sendCommand[0];
        long value  = sendCommand[1];
        return new long[]{id,value};
    }
    public String getMdiString()
    {
        String aux = mdiStrings.get(0);
        mdiStrings.remove(0);
        return aux;
    }
    /**
     * Proporciona los valores existentes en cola que son generados por los 
     * campos editables y que no pertenecen al teclado.
     * @return Existen tres casos.<br>
     * Caso 1. Si el el primer entero del arreglo es igual al valor del 
     * identificador DataCategory.Data.WORK_OFFSET, el arreglo constara de
     * cuatro enteros más, siendo el índice de la compensación de trabajo 
     * seguido de los nuevos valores del eje x, eje y y eje z.<br>
     * Caso 2. Si el el primer entero del arreglo es igual al valor del 
     * identificador DataCategory.Data.TOOL_OFFSET, el arreglo constara de
     * tres enteros más, siendo el índice de la herramienta seguido de los 
     * nuevos valores para la longitud y el radio o diámetro.<br>
     * Caso 3. En otro caso es un arreglo de dos enteros representando el identificador 
     * y valor respectivamente del dato modificado.<br>
     */
    public long[] getDataValue()
    {
        long[] sendingData = sendingDataValue.get(0);
        sendingDataValue.remove(0);
        if(sendingData[0] == Data.WORK_OFFSET)
            return new long[]{
                sendingData[0],
                sendingData[1],
                sendingData[2],
                sendingData[3]
                //sendingData[4],
            };
        if(sendingData[0] == Data.TOOL_OFFSET)
            return new long[]{
                sendingData[0],
                sendingData[1],
                sendingData[2],
                sendingData[3],
            };
        long id  = sendingData[0];
        long value  = sendingData[1];
        return new long[]{id,value};
    }
    /**
     * Comunica a la interfaz gráfica cambios generados por el teclado a los 
     * datos correspondientes.
     * @param id identificador del comando de teclado.
     * @param value nuevo valor.
     */
    public void setCommand(int id, int value)
    {
        data.setCommandValue(id,value);
    }
    public void setCommand(int id, long value)
    {
        //NewComp.proofFrame.addText("setCommand id = "+ id +" "+"value = "+ value +"");
        data.setCommandValue(id,(long)value);
    }
    /**
     * Comunica a la interfaz gráfica cambios generados en datos no presentes en los
     * comandos del teclado.
     * Como por ejemplo el cambio en las coordenadas de la posición actual.
     * @param id identificador del dato.
     * @param value nuevo valor del dato.
     */
    public void setDataValue(int id,int value)
    {
        //NewComp.proofFrame.addText("setCommand id = "+ id +" "+"value = "+ value +"");
        data.setDataValue(id,value);
    }
    public void setDataValue(int id,long value)
    {
        //NewComp.proofFrame.addText("setCommand id = "+ id +" "+"value = "+ value +"");
        data.setDataValue(id,(long)value);
    }
    /**
     * Informa si existen cambios generados por los controles del teclado.
     * @return true si existen ccambios en cola.<br>
     * false si no hay cambios
     */
    public boolean changeExists()
    {
        if(!commandSend.isEmpty())
            return true;
        else
            return false;
    }
    public boolean newMdiStringExist()
    {
        return !mdiStrings.isEmpty();
    }
    /**
     * Informa si se han editado valores de datos ajenos al teclado.
     * @return true si existen cambios.<br>
     * false si no hay cambios.
     */
    public boolean existChangedData()
    {
        if(!sendingDataValue.isEmpty())
            return true;
        else
            return false;
    }
    /**
     * Informa si existen tareas pendientes relativas a la edición de archivos.
     * return true si hay tareas pendientes.<br>
     * false si no hay tareas esperando
     */
    public boolean newTasksExists()
    {
        if(!taskSend.isEmpty())
            return true;
        else
            return false;
    }
    /**
     * Agrega comandos generados por los controles de la interfaz gráfica.
     * @param id identificador del comando
     * @param value nuevo valor
     */
    /*public static void addCommand(KbdCmdId.CmdId id, KbdCmdId.CmdValue value)
    {
        int[] newInteger = new int[2];
        newInteger[0] = id.getId();
        newInteger[1] = value.getValue();
        commandSend.add(newInteger);
    }*/
    /**
     * Agrega comandos generados por los controles de la interfaz gráfica.
     * @param id identificador del comando
     * @param value nuevo valor
     */
    /*public static void addCommand(KbdCmdId.CmdId id, Integer value)
    {
        int[] newInteger = new int[2];
        newInteger[0] = id.getId();
        newInteger[1] = value;
        commandSend.add(newInteger);
    }*/
    /**
     * Agrega en cola comandos generados por los controles de la interfaz gráfica.
     * @param id identificador del comando
     * @param value nuevo valor
     */
    /*public static void addCommand(KbdCmdId.CmdId id, int value)
    {
        int[] newInteger = new int[2];
        newInteger[0] = id.getId();
        newInteger[1] = value;
        commandSend.add(newInteger);
    }*/
    public static void addCommand(int id, int value)
    {
        long[] newInteger = new long[2];
        newInteger[0] = (long)id;
        newInteger[1] = (long)value;
        commandSend.add(newInteger);
    }
    public static void addCommand(int id, long value)
    {
        long[] newInteger = new long[2];
        //NewComp.proofFrame.addText("addCommand id = "+ id +" "+"value = "+ value +"");
        newInteger[0] = (long)id;
        newInteger[1] = value;
        commandSend.add(newInteger);
    }
    /**
     * Agrega en cola cambios realizados por la interfaz gráfica sobre datos.
     * @param id identificador del dato
     * @param value nuevo valor del dato
     */
    public static void addDataValue(int id, long value)
    {
        long[] newInteger = new long[2];
        newInteger[0] = (long)id;
        newInteger[1] = value;
        sendingDataValue.add(newInteger);
    }
    public static void addDataValue(int id, int value)
    {
        long[] newInteger = new long[2];
        newInteger[0] = (long)id;
        newInteger[1] = (long)value;
        sendingDataValue.add(newInteger);
    }
    /**
     * Agrega a la cola tares pendientes de edición y administración de archivos.
     * @param value valor correspondiente al identificador de la tarea.
     */
    public static void addTask(int value)
    {
        taskSend.add(new Integer(value));
    }
    /**
     * Agrega a la cola de datos unicamente cambios de las compensaciones de trabajo.
     * @param workOffsetIndex índice de la compensación de trabajo correspondiente.
     * @param x nuevo valor de compensación coorrespondiente al eje x.
     * @param y nuevo valor de compensación coorrespondiente al eje y.
     * @param z nuevo valor de compensación coorrespondiente al eje z.
     */
    /*public static void addWorkOffsets(int workOffsetIndex, 
                                      int x, 
                                      int y, 
                                      int z)
    {
        long[] newInteger = new long[5];
        newInteger[0] = Data.WORK_OFFSET;
        newInteger[1] = workOffsetIndex;
        newInteger[2] = x;
        newInteger[3] = y;
        newInteger[4] = z;
        sendingDataValue.add(newInteger);
    }*/
    public static void addWorkOffsets(int workOffsetIndex, 
                                      int indexAxis, 
                                      int value)
    {
        long[] newInteger = new long[4];
        newInteger[0] = Data.WORK_OFFSET;
        newInteger[1] = workOffsetIndex;
        newInteger[2] = indexAxis;
        newInteger[3] = value;
        sendingDataValue.add(newInteger);
    }
    /**
     * Agrega a la cola de datos unicamente cambios de las compensaciones de herramientas
     * @param toolOffsetIndex índice de la herramienta
     * @param lenght nueva longitud
     * @param radius nuevo radio o diámetro
     */
    public static void addToolOffsets(int toolOffsetIndex, 
                                      int lenght_radius, 
                                      int value)
    {
        long[] newInteger = new long[4];
        newInteger[0] = Data.TOOL_OFFSET;
        newInteger[1] = toolOffsetIndex;
        newInteger[2] = lenght_radius;
        newInteger[3] = value;
        sendingDataValue.add(newInteger);
    }
    public static void addMdiString(String string)
    {
        mdiStrings.add(string);
    }
    /*public static int[] getWorkOffsets()
    {
        if(!xyz.isEmpty())
        {
            int[] aux = xyz.get(0);
            xyz.remove(0);
            return aux;
        }else
            return new int[]{0,0,0};
    }*/
    /*public static int[] getToolOffsets()
    {
        if(!dimensions.isEmpty())
        {
            int[] aux = dimensions.get(0);
            dimensions.remove(0);
            return aux;
        }else
            return new int[]{0,0};
    }*/
    /**
     * Proporciona y borra la primera tarea de edición pendiente en la cola.
     * @return el identificador de la tarea
     */
    public int getTask()
    {
        Integer task = taskSend.get(0);
        taskSend.remove(0);
        return task.intValue();
    }
    /**
     * Actualiza el administrador de archivos
     */
    public void browserRefresh()
    {
        Mode.updateTable();
    }
    /**
     * Proporciona el nombre del archivo para realizar la ultima tarea en proceso
     * (Abrir, copiar, copiar como, renombrar, borrar).
     * @return una cadena que contiene el nombre de un archivo.
     */
    public String getFileName()
    {
        return Mode.getFileName();
    }
    /**
     * Proporciona el nuevo nombre de un archivo para la tarea de renombrar.
     * @return una cadena que contiene el nuevo nombre de un archivo.
     */
    public String getNewFileName()
    {
        return Mode.getNewFileName();
    }
    /**
     * Agrega una nueva línea de texto para ser visualizada en algún componente de la interfaz gráfica,
     * dependiendo del modo de operación.
     * @param line nueva línea de texto
     */
    public void setLineText(String line)
    {
        Mode.setLineText(line);
    }
    /**
     * Proporciona, una a una, líneas de texto del editor.
     * @return una cadena de texto o null si se llega al final del texto
     * u otro caso.
     */
    public String getLineText()
    {
        return Mode.getLineText();
    }
    /**
     * Agrega información de los archivos contenidos en un directorio.
     * @param name_ nombre del archivo
     * @param size_ tamaño del archivo
     * @param date_ fecha de modificación del archivo
     */
    public void addElement(String name_,int size_,String date_)
    {
        name.add(name_);
        size.add(new Integer(size_));
        date.add(date_);
    }
    /**
     * Proporciona un arreglo con los nombres agregados con el metodo addElement.
     * @return un arreglo de cadenas con nombres de archivos.
     */
    public static String[] getName()
    {
        String[] name_ = new String[name.size()];
        int total = name.size();
        for(int i = 0 ; i<total; i++)
        {
            name_[i] = name.get(0);
            name.remove(0);
        }
        name.clear();
        return name_;
    }
    /** 
     * Proporciona un arreglo con el tamaño de los archivos agregados con el metodo addElement.
     * @return un arreglo de objetos de tipo entero
     */
    public static Integer[] getSize()
    {
        Integer[] size_ = new Integer[size.size()];
        int total = size.size();
        for(int i = 0 ; i<total; i++)
        {
            size_[i] = size.get(0);
            size.remove(0);
        }
        size.clear();
        return size_;
    }
    /**
     * Proporciona un arreglo con las fechas de modificación  de los archivos agregados con el metodo addElement.
     * @return un arreglo de cadenas de texto.
     */
    public static String[] getDate()
    {
        String[] date_ = new String[date.size()];
        int total = date.size();
        for(int i = 0 ; i<total; i++)
        {
            date_[i] = date.get(0);
            date.remove(0);
        }
        date.clear();
        return date_;
    }
    /**
     * Establece el modo de operación.
     * @param value identificador del modo de operación.
     */
    public void selectForm(int value)
    {
        getMode(value).setMode();
    }
    /**
     * Proporciona un modo de operación.
     * @param value valor correspondiente a un modo de operación.
     * @return un objeto de clase Mode correspondiente al valor del
     * parámetro value
     */
    public Mode getMode(int value)
    {
        switch(value)
        {
            case KbdCmdId.CmdValue.MODE_MEMORY:
                return memoryMode;
            case KbdCmdId.CmdValue.MODE_MDI:
                return mdiMode;
            case KbdCmdId.CmdValue.MODE_FILE_MANAGER:
                return fileManagerMode;
            case KbdCmdId.CmdValue.MODE_EDITOR:
                return editorMode;
            case KbdCmdId.CmdValue.MODE_HANDWHEEL:
                return handwheelMode;
            case KbdCmdId.CmdValue.MODE_JOG:
                return jogMode;
            case KbdCmdId.CmdValue.MODE_RAPID:
                return rapidMode;
            case KbdCmdId.CmdValue.MODE_HOME:
                return zeroReturnMode;
            default:
                return zeroReturnMode;
        }
    }
    private static long[] removeCommand()
    {
        long[] element = commandSend.get(0);
        commandSend.remove(0);
        return element;
    }
    static
    {
        xyz = new ArrayList<long[]>(20);
        dimensions = new ArrayList<long[]>(20);
        sendingDataValue = new ArrayList<long[]>(10);
        commandSend = new ArrayList<long[]>(10);
        commandReceived = new ArrayList<long[]>(10);
        //stateSend = new ArrayList<int[]>(10);
        //stateReceived = new ArrayList<int[]>(10);
        name = new ArrayList<String>(15);
        size = new ArrayList<Integer>(15);
        date = new ArrayList<String>(15);
        taskSend = new ArrayList<Integer>(15);
        mdiStrings = new ArrayList<String>(15);
    }
    private static ArrayList<long[]> sendingDataValue;
    private static ArrayList<long[]> commandSend;
    private static ArrayList<long[]> commandReceived;
    //private static ArrayList<int[]> stateSend;
    //private static ArrayList<int[]> stateReceived;
    private static ArrayList<Integer> taskSend;
    private static ArrayList<String> name;
    private static ArrayList<Integer> size;
    private static ArrayList<String> date;
    private EditorMode editorMode;
    private MemoryMode memoryMode;
    private MdiMode mdiMode;
    private FileManagerMode fileManagerMode;
    private HandwheelMode handwheelMode;
    private JogMode jogMode;
    private RapidMode rapidMode;
    private ZeroReturnMode zeroReturnMode;
    private static ArrayList<long[]> xyz;
    private static ArrayList<long[]> dimensions;
    private static ArrayList<String> mdiStrings;
    private Data data;
}
